#include <iostream>

#include <string>
#include <log4cxx/logger.h>
#include <log4cxx/xml/domconfigurator.h>

#include "MetadataSvrClient.h"

#define THREAD_NUM 1 

#define DS_NOTIFY_DATA_FILE_INFO_REASON_FILE_OP 0

using std::cout;
using std::endl;
using std::ostringstream;

using namespace log4cxx;

pthread_mutex_t g_mutex;

string g_log_conf_file;

int parse_args(int argc, char * argv[]) {
        char c;
        while(-1 != (c = getopt(argc, argv, "l:"))) {
                switch(c) {
                        case 'l':
                                g_log_conf_file = optarg;
                                break;

                        default:
                                break;
                }
        }
}

int add_counter() {
        static int counter = 0;
        static time_t start_t = time(NULL);
        pthread_mutex_lock(&g_mutex);
        counter++;
        pthread_mutex_unlock(&g_mutex);
        if (counter % 1000 == 0) {
                cout << "rate:" << counter / (time(NULL) - start_t + 1) << endl;
        }
        return 1;
}

string md_file_info_2_string(MD_FILE_INFO info) {
	ostringstream oss;
	oss << "CLIENT_MD_RECORD: CLIENT_CRC:[";
	for (vector<uint32_t>::const_iterator iter = info.client_md_record.crcs.begin(); info.client_md_record.crcs.end() != iter; \
		iter++) {
		oss << " " << *iter;
	}
	oss << "] DATA_SVR_MD_RECORDS:[";
	for(map<int, DATA_SVR_MD_RECORD>::const_iterator iter = info.data_svr_md_records.begin(); \
		info.data_svr_md_records.end() != iter; iter++) {
		oss << " DATA_SVR_ID:" << iter->first << " FILE_SIZE:" << iter->second.file_size << " CRC:[";
		for(vector<uint32_t>::const_iterator iter1 = iter->second.crcs.begin(); iter->second.crcs.end() != iter1; \
			iter1++) {
			oss << " " << *iter1;
		}
		oss << "]";
	}
	oss << "]";
	return oss.str();
	
}
void * test_thread_routine(void * arg) {
        MetadataSvrClient * mdsc = (MetadataSvrClient *)arg;
        while (true) {
		int dir_id = rand();
		int file_id = rand();
		int ret = mdsc->create_md_file(dir_id, file_id);
		if (ret < 0) cout << "create ret:" << ret << endl;
		vector<uint32_t> client_crcs;
		vector<uint32_t> ds_crcs1, ds_crcs2;
		client_crcs.push_back(1);
		client_crcs.push_back(2);
		ds_crcs1.push_back(10);
		ds_crcs1.push_back(11);
		ds_crcs2.push_back(20);
		ds_crcs2.push_back(21);
		ret = mdsc->client_notify_client_data_info(dir_id, file_id, client_crcs);
		if (ret < 0) cout << "client notify client data info ret:" << ret << endl;
		ret = mdsc->data_svr_notify_data_file_info(dir_id, file_id, 10, 100, ds_crcs1, 0, \
								DS_NOTIFY_DATA_FILE_INFO_REASON_FILE_OP);
		if (ret < 0) cout << "data svr1 notify data file info ret:" << ret << endl;
		ret = mdsc->data_svr_notify_data_file_info(dir_id, file_id, 11, 101, ds_crcs2, 0, \
								DS_NOTIFY_DATA_FILE_INFO_REASON_FILE_OP);
		if (ret < 0) cout << "data svr2 notify data file info ret:" << ret << endl;
		MD_FILE_INFO info;
		ret = mdsc->get_md_file_info(1, 1, info);
		if (ret < 0) cout << "get md file info ret:" << ret << ", md file info:" << md_file_info_2_string(info) << endl;
		ret = mdsc->delete_md_file(dir_id, file_id);
		if (ret < 0) cout << "delete ret:" << ret << endl;
		int32_t new_ds_id;
		int32_t new_dir_id;
		int64_t new_file_id;
		ret = mdsc->alloc_ds_4_new_file(new_ds_id, new_dir_id, new_file_id);
		if (ret < 0) cout << "alloc ds error, ret:" << ret << endl;
		add_counter();
		return NULL;
        }
}

int test() {
        log4cxx::xml::DOMConfigurator::configure(g_log_conf_file.c_str());
        pthread_mutex_init(&g_mutex, NULL);
        srand(time(NULL));
        MetadataSvrClient mdsc;
        int ret = mdsc.init("127.0.0.1", 3503, 100, 5, 4, 3, -1);
        if (ret < 0) { cout << "meta data svr client init error:" << ret << endl; return -1; }
        pthread_t t[THREAD_NUM];
        for (int i = 0; i < THREAD_NUM; i++) {
                pthread_create(&t[i], NULL, test_thread_routine, &mdsc);
        }
        for (int i = 0; i < THREAD_NUM; i++) {
                pthread_join(t[i], NULL);
        }
        return 0;
}

int main(int argc, char * argv[]) {
	parse_args(argc, argv);
        return test();
}
